package com.example.a_java.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.a_java.common.Result;
import com.example.a_java.dto.LoanApplyDTO;
import com.example.a_java.dto.LoanDetailDTO;
import com.example.a_java.dto.LoanQueryDTO;
import com.example.a_java.entity.LoanApply;
import com.example.a_java.entity.LoanApplyFile;
import com.example.a_java.service.LoanApplyFileService;
import com.example.a_java.service.LoanApplyService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 贷款申请Controller
 */
@RestController
@RequestMapping("/loan/apply")
public class LoanApplyController {

    @Autowired
    private LoanApplyService loanApplyService;
    
    @Autowired
    private LoanApplyFileService loanApplyFileService;

    /**
     * 获取贷款列表
     */
    @GetMapping("/list")
    public Result<Map<String, Object>> list(
            @RequestParam(required = false) String loanNo,
            @RequestParam(required = false) String customerName,
            @RequestParam(required = false) String loanType,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) String orderBy,
            @RequestParam(defaultValue = "desc") String orderType) {
        
        // 构造查询对象
        LoanQueryDTO queryDTO = new LoanQueryDTO();
        queryDTO.setLoanNo(loanNo);
        queryDTO.setCustomerName(customerName);
        queryDTO.setLoanType(loanType);
        queryDTO.setStatus(status);
        queryDTO.setStartDate(startDate);
        queryDTO.setEndDate(endDate);
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setOrderBy(orderBy);
        queryDTO.setOrderType(orderType);
        
        // 查询数据
        Page<LoanApply> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<LoanApply> wrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (StringUtils.hasText(loanNo)) {
            wrapper.like(LoanApply::getApplyNo, loanNo);
        }
        
        if (StringUtils.hasText(customerName)) {
            wrapper.like(LoanApply::getCustomerName, customerName);
        }
        
        if (StringUtils.hasText(loanType)) {
            wrapper.eq(LoanApply::getLoanType, loanType);
        }
        
        if (StringUtils.hasText(status)) {
            // 转换状态字符串为状态码
            Integer statusCode = convertStatusToCode(status);
            if (statusCode != null) {
                wrapper.eq(LoanApply::getApplyStatus, statusCode);
            }
        }
        
        if (startDate != null) {
            wrapper.ge(LoanApply::getCreateTime, startDate.atStartOfDay());
        }
        
        if (endDate != null) {
            wrapper.le(LoanApply::getCreateTime, endDate.plusDays(1).atStartOfDay());
        }
        
        // 添加排序条件
        if (StringUtils.hasText(orderBy)) {
            if ("desc".equalsIgnoreCase(orderType)) {
                addOrderByDesc(wrapper, orderBy);
            } else {
                addOrderByAsc(wrapper, orderBy);
            }
        } else {
            wrapper.orderByDesc(LoanApply::getCreateTime);
        }
        
        // 分页查询
        page = loanApplyService.page(page, wrapper);
        
        // 构造返回结果
        List<Map<String, Object>> list = new ArrayList<>();
        for (LoanApply loanApply : page.getRecords()) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", loanApply.getApplyId());
            map.put("loanNo", loanApply.getApplyNo());
            map.put("customerName", loanApply.getCustomerName());
            map.put("loanType", loanApply.getLoanType());
            map.put("loanAmount", loanApply.getLoanAmount());
            map.put("loanTerm", loanApply.getLoanTerm());
            map.put("interestRate", loanApply.getInterestRate());
            map.put("monthlyPayment", loanApply.getMonthlyPayment());
            map.put("status", convertCodeToStatus(loanApply.getApplyStatus()));
            map.put("createTime", loanApply.getCreateTime());
            list.add(map);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("total", page.getTotal());
        result.put("list", list);
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);
        
        return Result.success(result);
    }

    /**
     * 获取贷款详情
     */
    @GetMapping("/{applyId}")
    public Result<LoanDetailDTO> getDetail(@PathVariable Long applyId) {
        // 查询贷款申请信息
        LoanApply loanApply = loanApplyService.getById(applyId);
        if (loanApply == null) {
            return Result.error("贷款不存在");
        }
        
        // 查询附件信息
        List<LoanApplyFile> files = loanApplyFileService.list(
                new LambdaQueryWrapper<LoanApplyFile>()
                        .eq(LoanApplyFile::getApplyId, applyId)
                        .eq(LoanApplyFile::getIsDeleted, 0)
        );
        
        // 构造返回结果
        LoanDetailDTO detailDTO = new LoanDetailDTO();
        detailDTO.setId(loanApply.getApplyId());
        detailDTO.setLoanNo(loanApply.getApplyNo());
        detailDTO.setCustomerName(loanApply.getCustomerName());
        detailDTO.setCustomerId(String.valueOf(loanApply.getCustId()));
        detailDTO.setPhone(loanApply.getPhone());
        detailDTO.setLoanType(loanApply.getLoanType());
        detailDTO.setLoanAmount(loanApply.getLoanAmount());
        detailDTO.setLoanTerm(loanApply.getLoanTerm());
        detailDTO.setInterestRate(loanApply.getInterestRate());
        detailDTO.setMonthlyPayment(loanApply.getMonthlyPayment());
        detailDTO.setPurpose(loanApply.getLoanPurpose());
        detailDTO.setRepaymentMethod(convertRepaymentMethodToString(loanApply.getRepayMethod()));
        detailDTO.setGuaranteeType(convertGuaranteeTypeToString(loanApply.getGuarMethod()));
        detailDTO.setCollateralValue(loanApply.getCollateralValue());
        detailDTO.setStatus(convertCodeToStatus(loanApply.getApplyStatus()));
        detailDTO.setApprovalStatus(loanApply.getApprovalStatus());
        detailDTO.setApprovalComment(loanApply.getApprovalComment());
        detailDTO.setApprovedAmount(loanApply.getApprovedAmount());
        detailDTO.setLoanDate(loanApply.getLoanDate());
        detailDTO.setFirstRepaymentDate(loanApply.getFirstRepaymentDate());
        detailDTO.setLastRepaymentDate(loanApply.getLastRepaymentDate());
        detailDTO.setCreateTime(loanApply.getCreateTime());
        detailDTO.setUpdateTime(loanApply.getUpdateTime());
        
        // 转换附件列表
        if (files != null && !files.isEmpty()) {
            List<LoanDetailDTO.LoanAttachmentDTO> attachments = files.stream().map(file -> {
                LoanDetailDTO.LoanAttachmentDTO attachment = new LoanDetailDTO.LoanAttachmentDTO();
                attachment.setId(String.valueOf(file.getFileId()));
                attachment.setFileName(file.getFileName());
                attachment.setFileType(file.getFileTypeString());
                attachment.setFileUrl(file.getFilePath());
                attachment.setUploadTime(file.getCreateTime());
                return attachment;
            }).collect(Collectors.toList());
            detailDTO.setAttachments(attachments);
        }
        
        return Result.success(detailDTO);
    }

    /**
     * 提交贷款申请
     */
    @PostMapping
    public Result<Map<String, Object>> apply(@RequestBody @Valid LoanApplyDTO applyDTO) {
        // 构造贷款申请对象
        LoanApply loanApply = new LoanApply();
        loanApply.setCustId(applyDTO.getCustomerId());
        loanApply.setCustomerName(applyDTO.getCustomerName());
        loanApply.setPhone(applyDTO.getPhone());
        loanApply.setLoanType(applyDTO.getLoanType());
        loanApply.setLoanAmount(applyDTO.getAmount());
        loanApply.setLoanTerm(applyDTO.getTerm());
        loanApply.setLoanPurpose(applyDTO.getPurpose());
        loanApply.setRepayMethod(convertRepaymentMethodToCode(applyDTO.getRepaymentMethod()));
        loanApply.setGuarMethod(convertGuaranteeTypeToCode(applyDTO.getGuaranteeType()));
        loanApply.setCollateralValue(applyDTO.getCollateralValue());
        
        // 设置申请状态为待审核
        loanApply.setApplyStatus(10);
        loanApply.setApplyTime(LocalDateTime.now());
        loanApply.setApplyNo(generateLoanNo());
        
        // 计算利率和月供简单示例
        loanApply.setInterestRate(new java.math.BigDecimal("4.8"));
        loanApply.setMonthlyPayment(calculateMonthlyPayment(
                applyDTO.getAmount(), 
                loanApply.getInterestRate(),
                applyDTO.getTerm()));
        
        // 保存贷款申请
        boolean success = loanApplyService.save(loanApply);
        
        if (success) {
            Map<String, Object> data = new HashMap<>();
            data.put("id", loanApply.getApplyId());
            data.put("loanNo", loanApply.getApplyNo());
            return Result.success(data);
        } else {
            return Result.error("申请提交失败");
        }
    }

    /**
     * 上传申请附件
     */
    @PostMapping("/upload")
    public Result<LoanDetailDTO.LoanAttachmentDTO> upload(
            @RequestParam("applyId") Long applyId,
            @RequestParam("fileType") String fileType,
            @RequestParam("file") MultipartFile file) {
        
        // 检查贷款申请是否存在
        LoanApply loanApply = loanApplyService.getById(applyId);
        if (loanApply == null) {
            return Result.error("贷款申请不存在");
        }
        
        // 检查文件类型
        if (!isValidFileType(fileType)) {
            return Result.error("文件类型不支持");
        }
        
        // 检查文件大小
        if (file.getSize() > 10 * 1024 * 1024) {
            return Result.error("文件大小超出限制");
        }
        
        try {
            // 保存文件(实际项目中应该保存到磁盘或云存储)
            String fileName = file.getOriginalFilename();
            String filePath = "/upload/files/" + fileName; // 模拟路径，实际应该上传并返回实际路径
            
            // 保存附件记录
            LoanApplyFile loanApplyFile = new LoanApplyFile();
            loanApplyFile.setApplyId(applyId);
            loanApplyFile.setFileType(convertFileTypeToCode(fileType));
            loanApplyFile.setFileTypeString(fileType);
            loanApplyFile.setFileName(fileName);
            loanApplyFile.setFilePath(filePath);
            loanApplyFile.setFileSize(file.getSize());
            
            loanApplyFileService.save(loanApplyFile);
            
            // 构造返回结果
            LoanDetailDTO.LoanAttachmentDTO attachment = new LoanDetailDTO.LoanAttachmentDTO();
            attachment.setId(String.valueOf(loanApplyFile.getFileId()));
            attachment.setFileName(fileName);
            attachment.setFileType(fileType);
            attachment.setFileUrl(filePath);
            attachment.setUploadTime(loanApplyFile.getCreateTime());
            
            return Result.success(attachment);
        } catch (Exception e) {
            return Result.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 修改贷款申请
     */
    @PutMapping
    public Result<Object> update(@RequestBody LoanApplyDTO applyDTO) {
        // 检查贷款申请是否存在
        if (applyDTO.getCustomerId() == null) {
            return Result.error("贷款ID不能为空");
        }
        
        LoanApply loanApply = loanApplyService.getById(applyDTO.getCustomerId());
        if (loanApply == null) {
            return Result.error("贷款申请不存在");
        }
        
        // 检查状态是否允许修改
        if (loanApply.getApplyStatus() != 10) {
            return Result.error("贷款状态不允许此操作");
        }
        
        // 更新基本信息
        if (StringUtils.hasText(applyDTO.getCustomerName())) {
            loanApply.setCustomerName(applyDTO.getCustomerName());
        }
        
        if (StringUtils.hasText(applyDTO.getPhone())) {
            loanApply.setPhone(applyDTO.getPhone());
        }
        
        if (StringUtils.hasText(applyDTO.getLoanType())) {
            loanApply.setLoanType(applyDTO.getLoanType());
        }
        
        if (applyDTO.getAmount() != null) {
            loanApply.setLoanAmount(applyDTO.getAmount());
            // 重新计算月供
            loanApply.setMonthlyPayment(calculateMonthlyPayment(
                    applyDTO.getAmount(), 
                    loanApply.getInterestRate(),
                    loanApply.getLoanTerm()));
        }
        
        if (applyDTO.getTerm() != null) {
            loanApply.setLoanTerm(applyDTO.getTerm());
            // 重新计算月供
            loanApply.setMonthlyPayment(calculateMonthlyPayment(
                    loanApply.getLoanAmount(), 
                    loanApply.getInterestRate(),
                    applyDTO.getTerm()));
        }
        
        if (StringUtils.hasText(applyDTO.getPurpose())) {
            loanApply.setLoanPurpose(applyDTO.getPurpose());
        }
        
        if (StringUtils.hasText(applyDTO.getRepaymentMethod())) {
            loanApply.setRepayMethod(convertRepaymentMethodToCode(applyDTO.getRepaymentMethod()));
        }
        
        if (StringUtils.hasText(applyDTO.getGuaranteeType())) {
            loanApply.setGuarMethod(convertGuaranteeTypeToCode(applyDTO.getGuaranteeType()));
        }
        
        if (applyDTO.getCollateralValue() != null) {
            loanApply.setCollateralValue(applyDTO.getCollateralValue());
        }
        
        // 保存更新
        boolean success = loanApplyService.updateById(loanApply);
        
        if (success) {
            return Result.success("申请修改成功");
        } else {
            return Result.error("申请修改失败");
        }
    }

    /**
     * 删除贷款申请
     */
    @DeleteMapping("/{applyId}")
    public Result<Object> delete(@PathVariable Long applyId) {
        // 检查贷款申请是否存在
        LoanApply loanApply = loanApplyService.getById(applyId);
        if (loanApply == null) {
            return Result.error("贷款申请不存在");
        }
        
        // 检查状态是否允许删除
        if (loanApply.getApplyStatus() != 10) {
            return Result.error("贷款状态不允许此操作");
        }
        
        // 逻辑删除贷款申请
        boolean success = loanApplyService.removeById(applyId);
        
        if (success) {
            return Result.success("申请删除成功");
        } else {
            return Result.error("申请删除失败");
        }
    }
    
    /**
     * 生成贷款编号
     */
    private String generateLoanNo() {
        return "LN" + LocalDate.now().toString().replace("-", "") 
                + String.format("%04d", (int)(Math.random() * 10000));
    }
    
    /**
     * 计算月供金额(等额本息)
     */
    private java.math.BigDecimal calculateMonthlyPayment(
            java.math.BigDecimal principal, 
            java.math.BigDecimal yearlyRate, 
            int months) {
        // 月利率
        java.math.BigDecimal monthlyRate = yearlyRate.divide(new java.math.BigDecimal("12"), 10, java.math.RoundingMode.HALF_UP)
                .divide(new java.math.BigDecimal("100"), 10, java.math.RoundingMode.HALF_UP);
        
        // (1+月利率)^贷款月数
        java.math.BigDecimal temp = monthlyRate.add(java.math.BigDecimal.ONE).pow(months);
        
        // 月供 = 本金 × 月利率 × 1+月利率^贷款月数 ÷ [(1+月利率^贷款月数 - 1]
        return principal.multiply(monthlyRate).multiply(temp)
                .divide(temp.subtract(java.math.BigDecimal.ONE), 2, java.math.RoundingMode.HALF_UP);
    }
    
    /**
     * 转换还款方式为代码
     */
    private Integer convertRepaymentMethodToCode(String repaymentMethod) {
        if ("equalInstallment".equals(repaymentMethod)) {
            return 1; // 等额本息
        } else if ("equalPrincipal".equals(repaymentMethod)) {
            return 2; // 等额本金
        } else if ("interestFirst".equals(repaymentMethod)) {
            return 3; // 先息后本
        } else if ("lumpSum".equals(repaymentMethod)) {
            return 4; // 一次性还本付息
        }
        return 1; // 默认等额本息
    }
    
    /**
     * 转换还款方式代码为字符串
     */
    private String convertRepaymentMethodToString(Integer repayMethod) {
        switch (repayMethod) {
            case 1: return "equalInstallment"; // 等额本息
            case 2: return "equalPrincipal"; // 等额本金
            case 3: return "interestFirst"; // 先息后本
            case 4: return "lumpSum"; // 一次性还本付息
            default: return "equalInstallment";
        }
    }
    
    /**
     * 转换担保方式为代码
     */
    private Integer convertGuaranteeTypeToCode(String guaranteeType) {
        if ("credit".equals(guaranteeType)) {
            return 1; // 信用
        } else if ("guarantee".equals(guaranteeType)) {
            return 2; // 保证
        } else if ("mortgage".equals(guaranteeType)) {
            return 3; // 抵押
        } else if ("pledge".equals(guaranteeType)) {
            return 4; // 质押
        }
        return 1; // 默认信用
    }
    
    /**
     * 转换担保方式代码为字符串
     */
    private String convertGuaranteeTypeToString(Integer guarMethod) {
        switch (guarMethod) {
            case 1: return "credit"; // 信用
            case 2: return "guarantee"; // 保证
            case 3: return "mortgage"; // 抵押
            case 4: return "pledge"; // 质押
            default: return "credit";
        }
    }
    
    /**
     * 转换文件类型为代码
     */
    private Integer convertFileTypeToCode(String fileType) {
        if ("idCard".equals(fileType)) {
            return 1; // 身份证
        } else if ("income".equals(fileType)) {
            return 2; // 收入证明
        } else if ("collateral".equals(fileType)) {
            return 3; // 抵押物证明
        } else {
            return 4; // 其他
        }
    }
    
    /**
     * 检查文件类型是否有效
     */
    private boolean isValidFileType(String fileType) {
        return "idCard".equals(fileType) || "income".equals(fileType) 
                || "collateral".equals(fileType) || "other".equals(fileType);
    }
    
    /**
     * 转换状态字符串为状态码
     */
    private Integer convertStatusToCode(String status) {
        switch (status) {
            case "pending": return 10; // 待审核
            case "approved": return 30; // 审核通过
            case "rejected": return 40; // 已拒绝
            default: return null;
        }
    }
    
    /**
     * 转换状态码为状态字符串
     */
    private String convertCodeToStatus(Integer statusCode) {
        switch (statusCode) {
            case 10: return "pending"; // 待审核
            case 20: return "pending"; // 审核中，也返回待审核
            case 30: return "approved"; // 审核通过
            case 40: return "rejected"; // 已拒绝
            default: return "pending";
        }
    }
    
    /**
     * 添加降序排序
     */
    private void addOrderByDesc(LambdaQueryWrapper<LoanApply> wrapper, String field) {
        switch (field) {
            case "createTime":
                wrapper.orderByDesc(LoanApply::getCreateTime);
                break;
            case "loanAmount":
                wrapper.orderByDesc(LoanApply::getLoanAmount);
                break;
            case "loanTerm":
                wrapper.orderByDesc(LoanApply::getLoanTerm);
                break;
            default:
                wrapper.orderByDesc(LoanApply::getCreateTime);
        }
    }
    
    /**
     * 添加升序排序
     */
    private void addOrderByAsc(LambdaQueryWrapper<LoanApply> wrapper, String field) {
        switch (field) {
            case "createTime":
                wrapper.orderByAsc(LoanApply::getCreateTime);
                break;
            case "loanAmount":
                wrapper.orderByAsc(LoanApply::getLoanAmount);
                break;
            case "loanTerm":
                wrapper.orderByAsc(LoanApply::getLoanTerm);
                break;
            default:
                wrapper.orderByAsc(LoanApply::getCreateTime);
        }
    }
} 
